<?php
/**
 * Firal CMS
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://firal.org/license
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to firal-dev@googlegroups.com so we can send you a copy immediately.
 *
 * @category   Firal
 * @package    Firal_App
 * @copyright  Copyright (c) 2008 Firal Developers
 * @license    http://firal.org/license     New BSD License
 * @version    $Id: App.php 11 2008-06-30 16:14:44Z pieterkokx $
 */

/**
 * @see Zend_Auth
 */
require_once 'Zend/Auth.php';
/**
 * @see Zend_Acl
 */
require_once 'Zend/Acl.php';
/**
 * @see Zend_Acl_Role
 */
require_once 'Zend/Acl/Role.php';
/**
 * @see Zend_Acl_Resource
 */
require_once 'Zend/Acl/Resource.php';
/**
 * @see Zend_Controller_Front
 */
require_once 'Zend/Controller/Front.php';

/**
 * @see Zend_Locale
 */
require_once 'Zend/Locale.php';
/**
 * @see Zend_Translate
 */
require_once 'Zend/Translate.php';
/**
 * @see Firal_Controller_Action_Helper_ThemeManager
 */
require_once 'Firal/Controller/Action/Helper/ThemeManager.php';

/**
 * Firal application runner
 *
 * @category   Firal
 * @package    Firal_App
 * @copyright  Copyright (c) 2008 MaakSite.nl Productions. (http://productions.maaksite.nl/)
 * @license    http://www.opensource.org/licenses/bsd-license.php     New BSD License
 */
final class Firal_App
{
    
    /**
     * Constructor, private for singleton
     * 
     * @return void
     */
    private function __construct()
    {}
    
    /**
     * Initialize the Firal CMS
     * 
     * @return void
     */
    public static function init()
    {
        $doctrineConfig = Zend_Registry::get('doctrine_config');
        
        // load all the models first
        Doctrine::loadModels($doctrineConfig['models_path']);
        
        self::_initAuth();
        
        self::_initLocale();
        
        self::_initMvc();
    }
    
    /**
     * Initialize the authentication and authorization part
     * 
     * @return void
     */
    protected static function _initAuth()
    {
        // $auth = Zend_Auth::getInstance();
        
        self::_initAcl();
    }
    
    /**
     * Initialize the Access Control List
     * 
     * @return void
     */
    protected static function _initAcl()
    {
        $firalCache = Zend_Registry::get('firal_cache');
        /* @var $firalCache Zend_Cache_Core */
        
        if (!($acl = $firalCache->load('firal_acl'))) {
            $query = Doctrine_Query::create()
                               ->select('g.name, p.name, p.resource')
                               ->from('AuthGroup g')
                               ->leftJoin('g.Permission p');
            $result = $query->execute(array(), Doctrine::HYDRATE_ARRAY);
            
            $acl = new Zend_Acl();
            
            $acl->add(new Zend_Acl_Resource('forum'));
            $acl->add(new Zend_Acl_Resource('firal'));
            
            foreach ($result as $group) {
                $acl->addRole(new Zend_Acl_Role($group['name']));
                if ($group['name'] == 'administrator') {
                    // administrator
                    $acl->allow($group['name']);
                } else {
                    $acl->deny($group['name']);
                }
                
                // add the allow rules
                foreach ($group['Permission'] as $permission) {
                    $acl->allow($group['name'], $permission['resource'], $permission['name']);
                }
            }
            
            $firalCache->save($acl, 'firal_acl', array('firal_core'), 2592000);
        }
        
        // just use the standard guest role
        $acl->addRole(new Zend_Acl_Role('currentuser'), 'test1');
        
        Zend_Registry::set('acl', $acl);
    }
    
    /**
     * Initialize the locale
     * 
     * @return void
     */
    protected static function _initLocale()
    {
        Zend_Locale::setDefault(Zend_Registry::get('config')->locale->default);
        
        $translate = new Zend_Translate('tmx', ROOT . '/data/translate/standard', null, array('scan' => Zend_Translate::LOCALE_DIRECTORY));
        
        Zend_Registry::set('Zend_Translate', $translate);
    }
    
    /**
     * Initialize the MVC structure
     * 
     * @return void
     */
    protected static function _initMvc()
    {
        $front = Zend_Controller_Front::getInstance();
        
        $front->addModuleDirectory(ROOT . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'modules');
        
        self::_initRoutes();
        
        $themeManager = new Firal_Controller_Action_Helper_ThemeManager('testtheme');
        
        $themeManager->setThemePath(ROOT . '/app/themes');
        
        Zend_Controller_Action_HelperBroker::addHelper($themeManager);
        
        // should be removed in production
        $front->throwExceptions(true);
        
        $front->dispatch();
    }
    
    /**
     * Create the routes
     * 
     * @return void
     */
    protected static function _initRoutes()
    {
        $front = Zend_Controller_Front::getInstance();
        
        // make sure the router is loaded
        $front->getRouter();
        
        $cache = Zend_Registry::get('firal_cache');
        /* @var $cache Zend_Cache_Core */
        
        if (!($router = $cache->load('firal_router'))) {
            $query = Doctrine_Query::create()
                           ->from('FiralRoute as r')
                           ->innerJoin('r.RouteValue as v');
            $routes = $query->execute(array(), Doctrine::HYDRATE_ARRAY);
            
            foreach ($routes as $route) {
                $routeValues = array();
                
                foreach ($route['RouteValue'] as $value) {
                    $routeValues[$value['name']] = $value['value'];
                }
                
                $router = $front->getRouter();
                
                switch ($route['type']) {
                    case 'regex':
                        $newRoute = new Zend_Controller_Router_Route_Regex($route['route'], $routeValues);
                        break;
                    case 'static':
                        $newRoute = new Zend_Controller_Router_Route_Static($route['route'], $routeValues);
                        break;
                    default:
                        $newRoute = new Zend_Controller_Router_Route($route['route'], $routeValues);
                        break;
                }
                
                $router->addRoute($route['name'], $newRoute);
            }
            
            $cache->save($router, 'firal_router', array('firal_core'), 2592000);
        } else {
            $front->setRouter($router);
        }
    }
}